package com.xiaohui.tool;

import javafx.util.Pair;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class HttpUtils {

    static CloseableHttpClient httpClient;

    static {

        // 请求类型
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();

        // 请求配置
        // 在网络状况不佳或服务响应缓慢的情况下快速失败，而不是长时间等待，这有助于提升用户体验和系统的整体响应速度。
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(Timeout.ofSeconds(1))
                .setConnectionRequestTimeout(Timeout.ofSeconds(1))
                .setResponseTimeout(Timeout.ofSeconds(1))
                .build();

        // httpclient连接池
        // 资源服用---避免频繁的创建和销毁连接，提高性能
        // 设置极限值，避免资源耗尽
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(500);
        connectionManager.setDefaultMaxPerRoute(500);
        connectionManager.setDefaultSocketConfig(
                // 灵活配置
                SocketConfig.custom()
                        .setSoTimeout(15, TimeUnit.SECONDS)
                        .setTcpNoDelay(true).build()
        );
        // 帮助维持长时间空闲连接的有效性，避免因为服务器端关闭了空闲连接而导致客户端发送请求失败的问题。
        connectionManager.setValidateAfterInactivity(TimeValue.ofSeconds(15));


        // 创建httpclient
        httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                // 自动重试禁用：
                // 可以防止HttpClient在遇到某些类型的错误时自动重试请求。
                // 对于幂等性要求高的操作，或者想要自己实现更复杂的重试逻辑的情况，这是很有帮助的。
                .disableAutomaticRetries()
                .build();
    }

      // post
    public static String post(String url, List<Pair<String, String>> pairList, Map<String, String> headerMap) throws Exception {
        // pair不强调映射
        url = url + "?" + buildParam(pairList);
        HttpPost httpPost = new HttpPost(url);
        if(Objects.nonNull(headerMap) && headerMap.size() > 0){
            headerMap.forEach((k,v)->{
                httpPost.addHeader(k,v);
            });
        }
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            return EntityUtils.toString(response.getEntity());
        } finally {
            if (response != null) {
                EntityUtils.consume(response.getEntity());
            }
        }
    }
    private static String buildParam(List<Pair<String, String>> pairList) {
        StringBuilder stringBuilder = new StringBuilder();
        for (Pair<String, String> pair : pairList) {
            stringBuilder.append(pair.getKey()).append("=").append(pair.getValue()).append("&");
            // ? name = zzz & age = 18
        }
        stringBuilder.setLength(stringBuilder.length() - 1);
        return stringBuilder.toString();
    }
}
